Option Strict On
Option Explicit On

Imports System

Public Class Tools
#Region "Utility methods"
   Public Shared Function IsTypeNameNumeric( _
            ByVal typeName As String) _
            As Boolean
      If typeName.ToLower().StartsWith("system.") Then
         If IsTypeNameInteger(typeName) Then
            Return True
         Else
            typeName = typeName.Substring(Len("system."))
            Select Case typeName.ToLower
               Case "double", "single", "decimal"
                  Return True
            End Select
         End If
      End If
      Return False
   End Function

   Public Shared Function IsTypeNameApproximate( _
            ByVal typeName As String) _
            As Boolean
      If typeName.StartsWith("system.", StringComparison.InvariantCultureIgnoreCase) Then
         typeName = typeName.Substring(Len("system."))
         Select Case typeName.ToLower
            Case "double", "single"
               Return True
         End Select
      End If
      Return False
   End Function

   Public Shared Function IsTypeNameInteger( _
           ByVal typeName As String) _
           As Boolean
      If typeName.ToLower().StartsWith("system.") Then
         typeName = typeName.Substring(Len("system."))
         Select Case typeName.ToLower
            Case "int32", "int16", "int64", "int32", _
                  "byte", "uint16", "uint64", "uint32", _
                   "sbyte"
               Return True
         End Select
      End If
      Return False
   End Function

   Public Shared Function IsTypeNameString( _
             ByVal typeName As String) _
             As Boolean
      If typeName.ToLower().StartsWith("system.") Then
         typeName = typeName.Substring(Len("system."))
         Select Case typeName.ToLower
            Case "string"
               Return True
         End Select
      End If
      Return False
   End Function

   Public Shared Function IsTypeNameDate( _
            ByVal typeName As String) _
            As Boolean
      If typeName.ToLower().StartsWith("system.") Then
         typeName = typeName.Substring(Len("system."))
         Select Case typeName.ToLower
            Case "datetime"
               Return True
         End Select
      End If
      Return False
   End Function

   Public Shared Function IsSqlTypeNameString( _
              ByVal typeName As String) _
              As Boolean

      Select Case typeName.ToLower
         Case "varchar", "char", "nvarchar", "nchar", "text"
            Return True
      End Select
      Return False
   End Function

   Public Shared Function IsSqlTypeNameVeryLarge( _
            ByVal sqlType As String) _
            As Boolean
      Return (String.Compare(sqlType, "text", StringComparison.InvariantCultureIgnoreCase) = 0 Or _
             String.Compare(sqlType, "ntext", StringComparison.InvariantCultureIgnoreCase) = 0 Or _
             String.Compare(sqlType, "image", StringComparison.InvariantCultureIgnoreCase) = 0)
   End Function

   Public Shared Function GetSingular(ByVal name As String) As String
      ' TODO: Replace with xml based system
      Dim testName As String
      If name Is Nothing Then
         Return ""
      Else
         testName = name.Trim
         If testName.ToLower.EndsWith("analyses") Then
            Return testName.Substring(0, testName.Length - 2) & "is"
         Else
            If testName.ToLower.EndsWith("children") Then
               Return testName.Substring(0, testName.Length - 8) & "Child"
               'ElseIf testName.ToLower.EndsWith("criteria") Then
               '   Return testName.Substring(0, testName.Length - 1) & "on"
            ElseIf testName.ToLower.EndsWith("clauses") Then
               Return testName.Substring(0, testName.Length - 1)
            ElseIf testName.ToLower.EndsWith("ss") Or Not testName.ToLower.EndsWith("s") Then
               ' This is generally not a plural    
               Return testName
            ElseIf testName.ToLower.EndsWith("us") Then
               ' This is generally not a plural
               Return testName
            ElseIf testName.ToLower.EndsWith("sses") Then
               Return testName.Substring(0, testName.Length - 2)
            ElseIf testName.ToLower.EndsWith("uses") Then
               Return testName.Substring(0, testName.Length - 2)
            ElseIf testName.ToLower.EndsWith("ies") Then
               ' NOTE: You can't tell from here if it used to be ey or y. You must
               '       add the specific cases important to you.
               Return testName.Substring(0, testName.Length - 3) & "y"
            ElseIf testName.ToLower.EndsWith("s") Then
               Return testName.Substring(0, testName.Length - 1)
            Else
               Return testName ' We shouldn't be able to get here
            End If
         End If
      End If
   End Function

   Public Shared Function GetPlural(ByVal name As String) As String
      ' TODO: Replace with xml based system
      ' Simple rules, you may need to expand these. Create new Case entries 
      ' above the Else for any exceptions important to you
      Dim testName As String
      If name Is Nothing Then
         Return ""
      Else
         testName = GetSingular(name)
         If testName.ToLower.EndsWith("analysis") Then
            Return testName.Substring(0, testName.Length - 2) + "es"
         Else
            If testName.ToLower.EndsWith("child") Then
               Return testName.Substring(0, testName.Length - 5) & "Children"
               'ElseIf testName.ToLower.EndsWith("criterion") Then
               '   Return testName.Substring(0, testName.Length - 2) & "a"
            ElseIf testName.ToLower.EndsWith("key") Then
               Return testName & "s"
            ElseIf testName.EndsWith("ey") Then
               Return testName.Substring(0, testName.Length - 2) & "ies"
            ElseIf testName.EndsWith("ay") Then
               Return testName.Substring(0, testName.Length) & "s"
            ElseIf testName.EndsWith("y") Then
               Return testName.Substring(0, testName.Length - 1) & "ies"
            ElseIf testName.EndsWith("ss") Then
               Return testName.Substring(0, testName.Length) & "es"
            ElseIf testName.EndsWith("us") Then
               Return testName.Substring(0, testName.Length) & "es"
            ElseIf testName.EndsWith("s") Then
               Return testName.Substring(0, testName.Length - 1) & "es"
            Else
               Return testName & "s"
            End If
         End If
      End If
   End Function

   Public Shared Function GetShortNetType(ByVal netType As String) As String
      'Dim shortNetType As String = netType
      'If shortNetType.ToLower.StartsWith("system.") Then
      '   shortNetType = shortNetType.Substring(7)
      'End If
      'Return shortNetType
      Return netType.Substring(netType.LastIndexOf(".") + 1)
   End Function

   Public Shared Function GetVbTypeAlias(ByVal netType As String) As String
      ' Fix arrays
      netType = GetLegalVBType(netType)

      Dim shortNetType As String = GetShortNetType(netType)
      Select Case shortNetType.ToLower()
         Case "boolean", "char", "byte", "double", "single", "decimal"
            Return shortNetType
         Case "int16"
            Return "Short"
         Case "int32"
            Return "Integer"
         Case "int64"
            Return "Long"
         Case "datetime"
            Return "Date"
         Case "string"
            Return "String"
         Case Else
            Return netType
      End Select
   End Function

   Public Shared Function GetLegalVBType(ByVal nettype As String) As String
      If nettype.Contains("[]") Then
         nettype = nettype.Replace("[]", "()")
      End If
      Return nettype
   End Function

   Public Shared Function GetCSharpTypeAlias(ByVal netType As String) As String
      ' Fix arrays
      If netType.Contains("()") Then
         netType = netType.Replace("()", "[]")
      End If

      ' Note: CSharp does not convert to lower for case insensitivity
      Dim shortNetType As String = GetShortNetType(netType)
      Select Case shortNetType
         Case "Boolean"
            Return "bool"
         Case "Char", "Byte", "Double", "Decimal", "SByte", "String"
            Return shortNetType.ToLower()
         Case "Single"
            Return "float"
         Case "Int16"
            Return "short"
         Case "Int32"
            Return "int"
         Case "Int64"
            Return "long"
         Case "UInt16"
            Return "ushort"
         Case "UInt32"
            Return "uint"
         Case "UInt64"
            Return "ulong"
         Case Else
            Return netType
      End Select

   End Function

   Public Shared Function GetCaption(ByVal name As String) As String
      Return SpaceAtCaps(name)
   End Function

   Private Shared Function SpaceAtCaps(ByVal s As String) As String
      ' The name is legacy, this also replaces underscores
      Dim chars() As Char = s.ToCharArray
      Dim sb As New Text.StringBuilder

      For i As Int32 = 0 To chars.GetUpperBound(0)
         If chars(i) = "_" Then
            sb.Append(" ")
         Else
            If (i > 0) AndAlso (IsSpaceChar(chars(i)) And Not IsSpaceChar(chars(i - 1))) Then
               sb.Append(" ")
            End If
            sb.Append(chars(i))
         End If
      Next
      Return sb.ToString
   End Function
   Private Shared Function IsSpaceChar(ByVal c As Char) As Boolean
      Return System.Char.IsUpper(c) Or System.Char.IsNumber(c)
   End Function

   Public Shared Function ExtractObjectName( _
            ByVal pattern As String, _
            ByVal name As String) As String
      Const searchFor As String = Constants.objectToken
      Dim index As Int32 = pattern.IndexOf(searchFor)
      Dim usePattern1 As String = pattern.Substring(0, index)
      Dim usePattern2 As String = pattern.Substring(index + searchFor.Length)
      Dim ret As String = Nothing
      Dim index1 As Int32
      If usePattern1.Length = 0 Then
         index1 = 0
      Else
         index1 = name.IndexOf(usePattern1)
      End If
      Dim position As Int32 = index1 + usePattern1.Length
      If index1 = 0 And name.Length > position Then
         Dim index2 As Int32
         If usePattern2.Length = 0 Then
            index2 = name.Length
         Else
            index2 = position + name.Substring(position).IndexOf(usePattern2)
         End If
         Dim length As Int32 = index2 - position
         If position >= 0 AndAlso length > 0 Then
            ret = name.Substring(position, length)
         End If
      End If
      Return ret
   End Function

   Public Shared Function ExpandWithObjectName( _
            ByVal pattern As String, _
            ByVal name As String) _
            As String
      Const searchFor As String = Constants.objectToken
      Return pattern.Replace(searchFor, name)
   End Function

   Public Shared Function IIf(Of T)(ByVal condition As Boolean, ByVal val1 As T, ByVal val2 As T) As T
      If condition Then
         Return val1
      Else
         Return val2
      End If
   End Function
#End Region


End Class
